import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QTreeWidget, QTableWidgetItem, QCheckBox, QTreeWidgetItem, \
    QVBoxLayout, QWidget, QPushButton, QHBoxLayout, QSizePolicy, QDialog
from PySide6.QtCore import Qt, QRect, QThread, QDateTime, Signal, Slot
from PySide6.QtCharts import QChartView, QChart, QScatterSeries, QValueAxis
from PySide6.QtGui import QColor
from Auxiliary_interface.production import Ui_Production  # 登录界面UI文件，并编写逻辑
import pymssql
import json                           # json数组文件的读写库
import numpy as np                    # 存储和处理大型矩阵阵列数组
from sklearn.cluster import AgglomerativeClustering  # K-means聚类算法模块
from sklearn.metrics import silhouette_score                 # 轮廓系数计算，选择最大的轮廓系数
import math

min_pizu = ""
clck_v = ""

horizontalheaderitem1 = ["选择", "坯组编号", "边号", "操作员", "填写时间", "开始时间", "结束时间"]

horizontalheaderitem2 = ["坯组编号", "板坯编号", "板坯顺序", "原料材质", "原料长度", "原料宽度", "原料厚度", "备注"]
# results1 = []        # A枪生产数据报表
# results1_B = []      # B枪生产数据报表
# results2 = []        # A枪原料数据报表
# results2_B = []      # B枪原料数据报表

duoxuan = []      # 多选框选中数据汇总

# pizu_change = {"A24090400": {"pizu": "A24090400", "1": "1", "2": "2", "3": "3", "4": "4", "max_bian": 4},
#                "A24090401": {"pizu": "A24090401", "1": "1", "2": "2", "3": "3", "4": "4", "max_bian": 4},
#                "A24090402": {"pizu": "A24090402", "1": "1", "2": "2", "3": "3", "4": "4", "max_bian": 4}}  #坯组编号的修改记录，写表格时进行初始化

# ------------------多线程------------
class Thread_started(QThread):
    # 输出信号
    e_hl_a = Signal()            # A 长宽错误输出
    e_hl_b = Signal()            # B 长宽错误输出
    e_wfp_a = Signal(str)        # A 修改后的临时坯组编号
    e_wfp_b = Signal(str)        # B 修改后的临时坯组编号
    pizu_out_a = Signal(int)     # A 坯组数量输出
    bianhao_out_a = Signal(int)  # A 边号数量输出
    pizu_out_b = Signal(int)     # B 坯组数量输出
    bianhao_out_b = Signal(int)  # B 边号数量输出

    def __init__(self, To_be_allocated_name1):
        super().__init__()
        from main import servermy, portmy, usermy, passwordmy, databasemy
        self.conn = pymssql.connect(server=servermy, port=portmy, user=usermy, password=passwordmy, database=databasemy,
                                    charset='utf8')
        self.cursor = self.conn.cursor()
        self.conn.autocommit(True)  # 设置是否自动提交事务
        self.pizu_change = {}       # 坯组聚类结果字典
        self.results1 = []          # 生产数据报表
        self.results2 = []          # 原料数据报表
        self.pizu_number = 0        # 页面设置坯组数量
        self.bian_number = 0        # 页面设置边数量

        self.To_be_allocated_name = [To_be_allocated_name1]

    def run(self):
        global min_pizu
        self.results2 = None
        self.pizu_change.clear()
        if len(self.To_be_allocated_name) > 1 or "无分配" in self.To_be_allocated_name[0]:
            # 基础去重（自动排序）
            self.To_be_allocated_name = np.unique(self.To_be_allocated_name)
            print(self.To_be_allocated_name)
            # print(self.To_be_allocated_name,len(self.To_be_allocated_name))
            print("无分配数据开始处理")
            combined_arr = np.empty((0, 2))
            for pizu_name in self.To_be_allocated_name:
                if pizu_name[0] == "A":
                    self.cursor.execute(
                        """SELECT
                                        ID,
                                        Z坐标
                                    FROM
                                        persons_A
                                    WHERE
                                        坯组编号 = %s
                                    """, pizu_name)
                if pizu_name[0] == "B":
                    self.cursor.execute(
                        """SELECT
                                        ID,
                                        Z坐标
                                    FROM
                                        persons_B
                                    WHERE
                                        坯组编号 = %s
                                    """, pizu_name)
                results = self.cursor.fetchall()  # 获取查询到的所有信息
                results = np.array(results)
                print("results", len(results))
                combined_arr = np.concatenate((combined_arr, results), axis=0)
                print("combined_arr", len(combined_arr))
            results_zh = np.transpose(combined_arr)  # np.transpose行列转换

            # labels = np.array([])  # 或者其他合适的默认值
            results_z = results_zh[1].reshape(-1, 1)  # 行列转换

            best_n_clusters = self.pizu_number  # 族,为页面设置值
            # print("最合适的族：", best_n_clusters)
            if self.To_be_allocated_name[0][0] == "A":
                self.pizu_out_a.emit(best_n_clusters)
            elif self.To_be_allocated_name[0][0] == "B":
                self.pizu_out_b.emit(best_n_clusters)
            agg_clustering = AgglomerativeClustering(n_clusters=best_n_clusters)  # 使用最合适的族进行运算
            labels = agg_clustering.fit_predict(results_z)
            # 计算每个簇的中心点
            unique_labels = np.unique(labels)  # 去重计算
            centroids = []
            for label in unique_labels:
                centroid = np.mean(results_z[labels == label], axis=0)
                centroids.append(centroid)
            centroids = np.array(centroids)

            # 按照第一个特征值对簇中心进行排序
            sorted_indices = np.argsort(centroids[:, 0])
            # 重新分配聚类标签
            sorted_labels = np.zeros_like(labels)
            for new_label, old_label in enumerate(sorted_indices):
                sorted_labels[labels == old_label] = new_label
            labels = sorted_labels

            labels = labels.reshape(-1, 1)
            results = np.append(combined_arr, labels, axis=1)
            # ------------第二步：根据Z坐标聚类结果更新数据库------------更新坯组编号信息-临时编号：待分配+YYMMHH+编号--------------
            if self.To_be_allocated_name[0][0] == "A":
                update_query = """
                                UPDATE persons_A
                                SET 坯组编号 = %s
                                WHERE ID = %s
                                """
            elif self.To_be_allocated_name[0][0] == "B":
                update_query = """
                                UPDATE persons_B
                                SET 坯组编号 = %s
                                WHERE ID = %s
                                """
            # 要更新的数据
            time = QDateTime.currentDateTime()  # 获取当前时间
            dateDisplay = time.toString('yyMMdd')  # 将当前时间转换成字符串类型
            # 获取历史坯组编号信息，提取与目前pi_zu1的相同的编号，如果有，则后半段编号排到多少了，接下来该是在此基础上增加new_value[2]，如果没有，则从0开始排，直接输出new_value[2]
            # 1、获取历史坯组编号
            if self.To_be_allocated_name[0][0] == "A":
                self.cursor.execute(
                    """SELECT
                        坯组编号
                        FROM
                        persons_A""")
                pi_zu1 = "A" + dateDisplay
            elif self.To_be_allocated_name[0][0] == "B":
                self.cursor.execute(
                    """SELECT
                        坯组编号
                        FROM
                        persons_B""")
                pi_zu1 = "B" + dateDisplay
            results0 = self.cursor.fetchall()  # 获取查询到的所有信息
            results_zh = np.transpose(results0)  # np.transpose行列转换
            unique_pizu = np.unique(results_zh[0])  # 坯组编号去重计算

            ls_pi_zu1 = pi_zu1 + "无分配"

            # print(pi_zu1)
            # 筛选出包含 pi_zu1 的项
            filtered_data = [item for item in unique_pizu if pi_zu1 in item]  # 正式编号
            ls_filtered_data = [item for item in unique_pizu if
                                ls_pi_zu1 in str(item.encode('latin1').decode('gbk'))]  # 临时编号
            if len(filtered_data) > 0:
                # 提取后两位数字最大值
                numbers1 = max([int(item[-2:]) for item in filtered_data])
            else:
                numbers1 = 0
            if len(ls_filtered_data) > 0:
                # 提取后两位数字最大值
                numbers = max([int(item[-2:]) for item in ls_filtered_data])
            else:
                numbers = 0

            min_pizu = pi_zu1 + f"{numbers1 + 1:02d}"
            for new_value in results:  # 数据库更新操作
                # 执行更新操作   格式化输出，
                # 待修改下方自动输出无分配的编号
                self.cursor.execute(update_query,
                                    (ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}", int(new_value[0])))
                # 提交事务
                self.conn.commit()
                # 更新预设字典内容                 临时编号                                          正式编号
                self.pizu_change[ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}"] = {
                    'pizu': pi_zu1 + f"{numbers1 + 1 + int(new_value[2]):02d}", '1': str(1), '2': str(2),
                    '3': str(3),
                    '4': str(4), 'max_bian': 4}
                if pi_zu1[0] == "A":
                    self.e_wfp_a.emit(ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}")
                elif pi_zu1[0] == "B":
                    self.e_wfp_b.emit(ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}")
            print("self.pizu_change", self.pizu_change)

                # # 获取该临时坯组编号的边号
                # self.cursor.execute(
                #     """SELECT
                #                     边号
                #                 FROM
                #                     persons
                #                 WHERE
                #                     坯组编号 = %s
                #                 """, pizu_name)
                # results = self.cursor.fetchall()          # 获取查询到的所有信息
                # results_zh = np.transpose(results)        # np.transpose行列转换
                # unique_pizu = np.unique(results_zh[0])    # 边号去重计算
                # # 1、获取历史坯组编号
                # self.cursor.execute(
                #     """SELECT
                #             坯组编号
                #         FROM
                #             production
                #             """)
                # results0 = self.cursor.fetchall()         # 获取查询到的所有信息
                # results_zh1 = np.transpose(results0)      # np.transpose行列转换
                # unique_pizu1 = np.unique(results_zh1[0])  # 坯组编号去重计算
                #
                # time = QDateTime.currentDateTime()        # 获取当前时间
                # # print(time)
                # dateDisplay = time.toString('yyMMdd')     # 将当前时间转换成字符串类型
                #
                # pi_zu1 = "A" + dateDisplay
                # # print(pi_zu1)
                # filtered_data = [item for item in unique_pizu1 if pi_zu1 in item]  # 正式编号
                # if len(filtered_data) > 0:
                #     # 提取后两位数字最大值
                #     numbers1 = max([int(item[-2:]) for item in filtered_data])
                # else:
                #     numbers1 = 0
                # zs_pizie = pi_zu1 + f"{numbers1 + 1:02d}"
                # for i in range(len(unique_pizu)//4):
                #     self.pizu_change[pizu_name] = {
                #         'pizu': pi_zu1 + f"{numbers1 + 1:02d}", '1': str(i*4+1), '2': str(i*4+2), '3': str(i*4+3),
                #         '4': str(i*4+4), 'max_bian': len(unique_pizu)}
                #
                # # -------------------------------第二步：将结果插入生产数据表格------------------------------
                # chkian = []
                # self.results1 = None
                # for bian in range(len(unique_pizu)):  # 根据边号数量编辑表格信息
                #     self.cursor.execute(
                #         """SELECT
                #                         MAX(日期时间) AS max_datetime,
                #                         MIN(日期时间) AS min_datetime
                #                     FROM
                #                         persons
                #                     WHERE
                #                         坯组编号 = %s
                #                     AND
                #                         边号 = %s
                #                         """, (pizu_name, str(bian+1)))
                #     results = self.cursor.fetchone()  # 获取查询到的最大值与最小值
                #     maxtime, mintime = results
                #     maxtime = maxtime.strftime('%Y/%m/%d %H:%M:%S')
                #     mintime = mintime.strftime('%Y/%m/%d %H:%M:%S')
                #     time = QDateTime.currentDateTime()
                #     datetimeDisplay = time.toString('yyyy-MM-dd hh:mm:ss.zzz')
                #     # 添加新行
                #
                #     new_row = np.array([(zs_pizie, bian+1, "张峰", datetimeDisplay, mintime, maxtime)], dtype=[
                #         ('pizie', 'U20'),
                #         ('bian', int),
                #         ('name', 'U10'),  # U10 表示最多10个字符的Unicode字符串
                #         ('datetimeDisplay', 'object'),  # 使用 'object' 类型来存储 datetime 对象
                #         ('mintime', 'object'),
                #         ('maxtime', 'object')
                #     ])
                #     if self.results1 is None:
                #         self.results1 = np.array([], dtype=new_row.dtype)
                #     self.results1 = np.append(self.results1, new_row, axis=0)
                #     # ----------------------第五步：表二信息填充：原料信息填充---------------------
                #     self.cursor.execute(
                #         """SELECT
                #                         MAX(X坐标) AS max_x,
                #                         MIN(X坐标) AS min_x,
                #                         MAX(Y坐标) AS max_y,
                #                         MIN(Y坐标) AS min_y,
                #                         MAX(Z坐标) AS max_z,
                #                         MIN(Z坐标) AS min_z
                #                     FROM
                #                         persons
                #                     WHERE
                #                         坯组编号 = %s
                #                     AND
                #                         边号 = %s
                #                         """, (pizu_name, bian+1))
                #     max_x, min_x, max_y, min_y, max_z, min_z = self.cursor.fetchone()  # 获取查询到的最大值与最小值
                #     # print(max_x,min_x,max_y,min_y,max_z,min_z)
                #     max_A = math.sqrt((max_x - min_x) ** 2 + (max_y - min_y) ** 2)  # 根号（x平方+y平方）
                #     max_A = math.sqrt(float(max_A) ** 2 + (float(max_z) - float(min_z)) ** 2)
                #     # print("max_A", max_A)
                #     chkian.append(max_A)
                # # 创建一维数组
                # one_d_array = np.array(chkian)
                # # 将一维数组转换为1列的二维数组
                # chkian = one_d_array[:, np.newaxis]
                # agg_clustering = AgglomerativeClustering(n_clusters=2)  # 使用最合适的族进行运算
                # labels = agg_clustering.fit_predict(chkian)  # 获得边号列
                # chang = 0
                # kuan = 0
                #
                # for i, view in enumerate(labels):
                #     if view == 0:
                #         if chang != 0:
                #             if chang - chkian[i] < 10:
                #                 chang = chang + chkian[i]
                #                 chang = chang / 2 + 20
                #                 continue
                #             else:
                #                 print("长错误")
                #         chang = chang + chkian[i]
                #     elif view == 1:
                #         if kuan != 0:
                #             if kuan - chkian[i] < 10:
                #                 kuan = kuan + chkian[i]
                #                 kuan = kuan / 2 + 20
                #                 continue
                #             else:
                #                 print("宽错误")
                #         kuan = kuan + chkian[i]
                # # 原料信息的填充
                # for i in range(1, 3):
                #     #print(zs_pizie)
                #
                #     new_row = np.array([(zs_pizie, "/", i, "/", chang, kuan, 0, "/")], dtype=[
                #         ('pizie', 'U20'),
                #         ('banpi', 'U10'),
                #         ('bian', int),
                #         ('caizhi', 'U10'),  # U10 表示最多10个字符的Unicode字符串
                #         ('chang', int),  # 使用 'object' 类型来存储 datetime 对象
                #         ('kuan', int),
                #         ('gao', int),
                #         ('beizu', 'U50')
                #     ])
                #     if self.results2 is None:
                #         self.results2 = np.array([], dtype=new_row.dtype)
                #     # print(results2)
                #     self.results2 = np.append(self.results2, new_row, axis=0)
                # self.cursor.close()
                # self.conn.close()
        else:
            # -------------------第一步：根据Z坐标聚类--------------------
            self.To_be_allocated_name = self.To_be_allocated_name[0]
            print("常规数据开始处理")
            if self.To_be_allocated_name[0] == "A":
                # print("A数据表数据获取", self.To_be_allocated_name)
                self.cursor.execute(
                    """SELECT
                                    ID,
                                    Z坐标
                                FROM
                                    persons_A
                                WHERE
                                    坯组编号 = %s
                                """, self.To_be_allocated_name)
            elif self.To_be_allocated_name[0] == "B":
                # print("B数据表数据获取", self.To_be_allocated_name)
                self.cursor.execute(
                    """SELECT
                                    ID,
                                    Z坐标
                                FROM
                                    persons_B
                                WHERE
                                    坯组编号 = %s
                                """, self.To_be_allocated_name)
            results = self.cursor.fetchall()  # 获取查询到的所有信息
            results_zh = np.transpose(results)  # np.transpose行列转换

            # print("results_zh", results_zh)

            # labels = np.array([])  # 或者其他合适的默认值
            if (np.max(results_zh[1]) - np.min(results_zh[1])) > 100:  # 判断Z轴峰值差值是否大于100，如果大于100说明可能为多组板叠加焊接，判断最合适的族
                print("大于100，开始判断族")
                results_z = results_zh[1].reshape(-1, 1)  # 行列转换
                # print("results_z", len(results_z))
                max_clusters = 4  # 最大族为6
                silhouette_scores = []
                for n_clusters in range(2, max_clusters + 1):
                    # print("尝试族：", n_clusters)
                    agg_clustering = AgglomerativeClustering(n_clusters=n_clusters)
                    # print("agg_clustering", agg_clustering)
                    labels = agg_clustering.fit_predict(results_z)
                    # print("labels", labels)
                    score = silhouette_score(results_z, labels)
                    # print("score", score)
                    silhouette_scores.append(score)
                    print("完毕一次")

                best_n_clusters = np.argmax(silhouette_scores) + 2  # 最合适的族
                # print("最合适的族：", best_n_clusters)
                if self.To_be_allocated_name[0] == "A":
                    self.pizu_out_a.emit(best_n_clusters)
                elif self.To_be_allocated_name[0] == "B":
                    self.pizu_out_b.emit(best_n_clusters)
                agg_clustering = AgglomerativeClustering(n_clusters=best_n_clusters)  # 使用最合适的族进行运算
                labels = agg_clustering.fit_predict(results_z)
                # 计算每个簇的中心点
                unique_labels = np.unique(labels)  # 去重计算
                centroids = []
                for label in unique_labels:
                    centroid = np.mean(results_z[labels == label], axis=0)
                    centroids.append(centroid)
                centroids = np.array(centroids)

                # 按照第一个特征值对簇中心进行排序
                sorted_indices = np.argsort(centroids[:, 0])
                # 重新分配聚类标签
                sorted_labels = np.zeros_like(labels)
                for new_label, old_label in enumerate(sorted_indices):
                    sorted_labels[labels == old_label] = new_label
                labels = sorted_labels
                # 聚类标签与数据库数组合并
            else:
                # print("单板坯组，")
                labels = np.zeros(len(results))
            labels = labels.reshape(-1, 1)
            results = np.append(results, labels, axis=1)
            # ------------第二步：根据Z坐标聚类结果更新数据库------------更新坯组编号信息-临时编号：待分配+YYMMHH+编号--------------
            if self.To_be_allocated_name[0] == "A":
                update_query = """
                    UPDATE persons_A
                    SET 坯组编号 = %s
                    WHERE ID = %s
                    """
            elif self.To_be_allocated_name[0] == "B":
                update_query = """
                    UPDATE persons_B
                    SET 坯组编号 = %s
                    WHERE ID = %s
                    """
            # 要更新的数据
            time = QDateTime.currentDateTime()      # 获取当前时间
            dateDisplay = time.toString('yyMMdd')   # 将当前时间转换成字符串类型
            # 获取历史坯组编号信息，提取与目前pi_zu1的相同的编号，如果有，则后半段编号排到多少了，接下来该是在此基础上增加new_value[2]，如果没有，则从0开始排，直接输出new_value[2]
            # 1、获取历史坯组编号
            if self.To_be_allocated_name[0] == "A":
                self.cursor.execute(
                    """SELECT
                        坯组编号
                        FROM
                        persons_A""")
                pi_zu1 = "A" + dateDisplay
            elif self.To_be_allocated_name[0] == "B":
                self.cursor.execute(
                    """SELECT
                        坯组编号
                        FROM
                        persons_B""")
                pi_zu1 = "B" + dateDisplay
            results0 = self.cursor.fetchall()       # 获取查询到的所有信息
            results_zh = np.transpose(results0)     # np.transpose行列转换
            unique_pizu = np.unique(results_zh[0])  # 坯组编号去重计算

            ls_pi_zu1 = pi_zu1 + "无分配"

            # print(pi_zu1)
            # 筛选出包含 pi_zu1 的项
            filtered_data = [item for item in unique_pizu if pi_zu1 in item]                                             # 正式编号
            ls_filtered_data = [item for item in unique_pizu if ls_pi_zu1 in str(item.encode('latin1').decode('gbk'))]   # 临时编号
            if len(filtered_data) > 0:
                # 提取后两位数字最大值
                numbers1 = max([int(item[-2:]) for item in filtered_data])
            else:
                numbers1 = 0
            if len(ls_filtered_data) > 0:
                # 提取后两位数字最大值
                numbers = max([int(item[-2:]) for item in ls_filtered_data])
            else:
                numbers = 0

            min_pizu = pi_zu1 + f"{numbers1 + 1:02d}"
            for new_value in results:  # 数据库更新操作
                # 执行更新操作   格式化输出，
                # 待修改下方自动输出无分配的编号
                self.cursor.execute(update_query, (ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}", int(new_value[0])))
                # 提交事务
                self.conn.commit()
                # 更新预设字典内容                 临时编号                                          正式编号
                self.pizu_change[ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}"] = {
                    'pizu': pi_zu1 + f"{numbers1 + 1 + int(new_value[2]):02d}", '1': str(1), '2': str(2), '3': str(3),
                    '4': str(4), 'max_bian': 4}
                if pi_zu1[0] == "A":
                    self.e_wfp_a.emit(ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}")
                elif pi_zu1[0] == "B":
                    self.e_wfp_b.emit(ls_pi_zu1 + f"{numbers + 1 + int(new_value[2]):02d}")
            print("self.pizu_change",self.pizu_change)
            # -----"------------------第三步：坯组边号分配操作--------------------根据每个坯组编号的转台与枪角度聚类--------------------
            pi_zu = []
            self.results1 = None
            self.results2 = None
            # 遍历字典的键
            for key, view in self.pizu_change.items():
                pi_zu.append(key)  # 坯组编号获取
            for pizie in pi_zu:
                chkian = []
                zs_pizie = self.pizu_change[pizie]['pizu']  # 正式坯组编号
                if self.To_be_allocated_name[0] == "A":
                    self.cursor.execute(
                        """SELECT
                             ID
                            ,R角度
                            ,转台角度
                        FROM
                            persons_A
                        WHERE
                            坯组编号 = %s  
                            """, pizie)
                elif self.To_be_allocated_name[0] == "B":
                    self.cursor.execute(
                        """SELECT
                             ID
                            ,R角度
                            ,转台角度
                        FROM
                            persons_B
                        WHERE
                            坯组编号 = %s  
                            """, pizie)
                results = self.cursor.fetchall()  # 获取查询到的所有信息
                # print("1", results)
                # 剔除第一列（索引为0）
                results_z = np.delete(results, 0, axis=1)
                agg_clustering = AgglomerativeClustering(n_clusters=4)  # 使用最合适的族进行运算
                # print("results_z", results_z)
                if self.To_be_allocated_name[0] == "A":
                    self.bianhao_out_a.emit(4)
                elif self.To_be_allocated_name[0] == "B":
                    self.bianhao_out_b.emit(4)
                labels = agg_clustering.fit_predict(results_z)          # 获得边号列
                Serial_cun = np.unique(labels)                          # 坯组编号去重计算-识别到的边号
                labels = labels.reshape(-1, 1)
                results = np.append(results, labels, axis=1)            # 添加一列
                # ---------------------------------更新数据库：边号信息---------------------------------
                if self.To_be_allocated_name[0] == "A":
                    update_query = """
                        UPDATE persons_A
                        SET 边号 = %s
                        WHERE ID = %s
                        """
                elif self.To_be_allocated_name[0] == "B":
                    update_query = """
                        UPDATE persons_B
                        SET 边号 = %s
                        WHERE ID = %s
                        """
                for new_value in results:  # 数据库更新操作    将边号嵌入数据表
                    # 执行更新操作
                    self.cursor.execute(update_query, (int(new_value[3]) + 10, int(new_value[0])))
                    # 提交事务
                    self.conn.commit()
                # 根据数据表边号的起始时间进行排序
                paixu = []
                for bian in Serial_cun:
                    if self.To_be_allocated_name[0] == "A":
                        self.cursor.execute(
                            """SELECT
                                MIN(日期时间) AS min_datetime
                            FROM
                                persons_A
                            WHERE
                                坯组编号 = %s
                            AND
                                边号 = %d  
                                """, (pizie, int(bian) + 10))
                    elif self.To_be_allocated_name[0] == "B":
                        self.cursor.execute(
                            """SELECT
                                MIN(日期时间) AS min_datetime
                            FROM
                                persons_B
                            WHERE
                                坯组编号 = %s
                            AND
                                边号 = %d  
                                """, (pizie, int(bian) + 10))
                    results = self.cursor.fetchone()  # 获取查询到的最大值与最小值
                    paixu.append([int(bian) + 10, results[0]])
                sorted_dict2 = sorted(paixu, key=lambda item: item[1])  # 根据获取到的时间排序结果
                # print(sorted_dict2)
                # 根据排序结果修改之前的边号
                results_zh = np.transpose(sorted_dict2)  # np.transpose行列转换
                results_z = results_zh[0]
                # print(results_z)
                if self.To_be_allocated_name[0] == "A":
                    update_query = """
                        UPDATE persons_A
                        SET 边号 = %d
                        WHERE 边号 = %d
                        AND 坯组编号 = %s
                        """
                elif self.To_be_allocated_name[0] == "B":
                    update_query = """
                        UPDATE persons_B
                        SET 边号 = %d
                        WHERE 边号 = %d
                        AND 坯组编号 = %s
                        """
                for new_Serial, new_value in enumerate(results_z):  # 数据库更新操作    将边号嵌入数据表
                    # print(new_value)
                    # print(new_label)
                    # 执行更新操作
                    self.cursor.execute(update_query, (int(new_Serial) + 1, int(new_value), pizie))
                    # 提交事务
                    self.conn.commit()

                # -------------------------------第四步：将结果插入生产数据表格------------------------------
                for bian in range(len(Serial_cun)):  # 编辑表格
                    bian = int(bian) + 1
                    if self.To_be_allocated_name[0] == "A":
                        self.cursor.execute(
                            """SELECT
                                MAX(日期时间) AS max_datetime,
                                MIN(日期时间) AS min_datetime
                            FROM
                                persons_A
                            WHERE
                                坯组编号 = %s
                            AND
                                边号 = %s  
                                """, (pizie, bian))
                    elif self.To_be_allocated_name[0] == "B":
                        self.cursor.execute(
                            """SELECT
                                MAX(日期时间) AS max_datetime,
                                MIN(日期时间) AS min_datetime
                            FROM
                                persons_B
                            WHERE
                                坯组编号 = %s
                            AND
                                边号 = %s  
                                """, (pizie, bian))
                    results = self.cursor.fetchone()  # 获取查询到的最大值与最小值
                    maxtime, mintime = results
                    maxtime = maxtime.strftime('%Y/%m/%d %H:%M:%S')
                    mintime = mintime.strftime('%Y/%m/%d %H:%M:%S')
                    time = QDateTime.currentDateTime()
                    datetimeDisplay = time.toString('yyyy-MM-dd hh:mm:ss')      # 填写时间精确到秒
                    # 添加新行

                    new_row = np.array([(zs_pizie, bian, "张峰", datetimeDisplay, mintime, maxtime)], dtype=[
                        ('pizie', 'U20'),
                        ('bian', int),
                        ('name', 'U10'),                # U10 表示最多10个字符的Unicode字符串
                        ('datetimeDisplay', 'object'),  # 使用 'object' 类型来存储 datetime 对象
                        ('mintime', 'object'),
                        ('maxtime', 'object')
                    ])
                    if self.results1 is None:
                        self.results1 = np.array([], dtype=new_row.dtype)
                    self.results1 = np.append(self.results1, new_row, axis=0)
                    # ----------------------第五步：表二信息填充：原料信息填充---------------------
                    # print("编号：", pizie, "边号：", bian)
                    if self.To_be_allocated_name[0] == "A":
                        self.cursor.execute(
                            """SELECT
                                MAX(X坐标) AS max_x,
                                MIN(X坐标) AS min_x,
                                MAX(Y坐标) AS max_y,
                                MIN(Y坐标) AS min_y,
                                MAX(Z坐标) AS max_z,
                                MIN(Z坐标) AS min_z
                            FROM
                                persons_A
                            WHERE
                                坯组编号 = %s
                            AND
                                边号 = %s  
                                """, (pizie, bian))
                    elif self.To_be_allocated_name[0] == "B":
                        self.cursor.execute(
                            """SELECT
                                MAX(X坐标) AS max_x,
                                MIN(X坐标) AS min_x,
                                MAX(Y坐标) AS max_y,
                                MIN(Y坐标) AS min_y,
                                MAX(Z坐标) AS max_z,
                                MIN(Z坐标) AS min_z
                            FROM
                                persons_B
                            WHERE
                                坯组编号 = %s
                            AND
                                边号 = %s  
                                """, (pizie, bian))
                    max_x, min_x, max_y, min_y, max_z, min_z = self.cursor.fetchone()  # 获取查询到的最大值与最小值
                    # print(max_x, min_x, max_y, min_y, max_z, min_z)
                    max_A = math.sqrt((max_x - min_x) ** 2 + (max_y - min_y) ** 2)  # 根号（x平方+y平方）
                    max_A = math.sqrt(float(max_A) ** 2 + (float(max_z) - float(min_z)) ** 2)
                    # print("max_A", max_A)
                    chkian.append(max_A)
                # 创建一维数组
                one_d_array = np.array(chkian)
                # 将一维数组转换为1列的二维数组
                chkian = one_d_array[:, np.newaxis]
                agg_clustering = AgglomerativeClustering(n_clusters=2)  # 使用最合适的族进行运算
                labels = agg_clustering.fit_predict(chkian)  # 获得边号列
                chang = 0
                kuan = 0
                # print(labels)
                for i, view in enumerate(labels):
                    if view == 0:
                        if chang != 0:
                            if chang - chkian[i] < 100:
                                chang = chang + chkian[i]
                                chang = chang / 2 + 20
                                continue
                            else:
                                if self.To_be_allocated_name[0] == "A":
                                    self.e_hl_a.emit()
                                elif self.To_be_allocated_name[0] == "B":
                                    self.e_hl_b.emit()
                                print("长错误")
                                # self.label_4.setStyleSheet("color: blue")
                                # self.label_4.setText('提交成功')
                        chang = chang + chkian[i]
                    elif view == 1:
                        if kuan != 0:
                            if kuan - chkian[i] < 100:
                                kuan = kuan + chkian[i]
                                kuan = kuan / 2 + 20
                                continue
                            else:
                                if self.To_be_allocated_name[0] == "A":
                                    self.e_hl_a.emit()
                                elif self.To_be_allocated_name[0] == "B":
                                    self.e_hl_b.emit()
                                print("宽错误")
                                # self.label_4.setStyleSheet("color: blue")
                                # self.label_4.setText('提交成功')
                        kuan = kuan + chkian[i]
                # 原料信息的填充
                for i in range(1, 3):
                    # print(zs_pizie)
                    new_row = np.array([(zs_pizie, "/", i, "/", chang, kuan, 0, "/")], dtype=[
                        ('pizie', 'U20'),
                        ('banpi', 'U10'),
                        ('bian', int),
                        ('caizhi', 'U10'),       # U10 表示最多10个字符的Unicode字符串
                        ('chang', int),          # 使用 'object' 类型来存储 datetime 对象
                        ('kuan', int),
                        ('gao', int),
                        ('beizu', 'U50')
                    ])
                    if self.results2 is None:
                        self.results2 = np.array([], dtype=new_row.dtype)
                    self.results2 = np.append(self.results2, new_row, axis=0)
            # self.cursor.close()
            # self.conn.close()

class Ui_shengchan(Ui_Production, QDialog):
    def __init__(self, To_be_allocated_name):
        super().__init__()
        self.setupUi(self)
        # print(222333, To_be_allocated_name)
        self.colors = [  # 不同曲线对应的颜色
            QColor(255, 0, 0), QColor(0, 255, 0), QColor(0, 0, 255), QColor(128, 0, 128)]
        # ----------------------多线程初始化---------------------
        self.Thread1 = Thread_started("A待分配"+To_be_allocated_name)
        self.Thread1.started.connect(self.thread_start)
        self.Thread1.finished.connect(self.Thread1.quit)
        # self.Thread1.finished.connect(self.Thread1.deleteLater)
        self.Thread1.finished.connect(self.thread_finished)

        self.Thread1_B = Thread_started("B待分配"+To_be_allocated_name)
        self.Thread1_B.started.connect(self.thread_start_B)
        self.Thread1_B.finished.connect(self.Thread1_B.quit)
        # self.Thread1_B.finished.connect(self.Thread1_B.deleteLater)
        self.Thread1_B.finished.connect(self.thread_finished_B)
        # -----------------------数据库初始化开启-------------------
        from main import servermy, portmy, usermy, passwordmy, databasemy
        self.conn = pymssql.connect(server=servermy, port=portmy, user=usermy, password=passwordmy, database=databasemy,
                                    charset='utf8')
        # self.label.setStyleSheet("color: green")
        # self.label.setText('数据库链接成功')
        self.label_14.setStyleSheet("color: green")
        self.label_14.setText('A过程无错误')
        self.label_15.setStyleSheet("color: green")
        self.label_15.setText('B过程无错误')
        self.cursor = self.conn.cursor()
        self.conn.autocommit(True)  # 设置是否自动提交事务

        # ------------------------生产信息数据-----------------------
        self.tableWidget.rows = None  # 初始化点击行参数
        self.tableWidget.columns = None  # 初始化点击列参数
        self.tableWidget_2.rows = None
        self.tableWidget_2.columns = None
        self.tableWidget_3.rows = None
        self.tableWidget_3.columns = None
        self.tableWidget_4.rows = None
        self.tableWidget_4.columns = None
        self.wfp_allocated_name_A = []    # 无分配坯组编号数据名称 A
        self.wfp_allocated_name_B = []    # 无分配坯组编号数据名称 B
        # ---------------------输入框初始化--------------------
        # self.lineEdit_2.setText("4")
        # ------------------------------A枪 按钮事件绑定--------------------------------
        # self.pushButton_5.clicked.connect(self.pushButton_5_clicked)    # 链接数据库
        # self.pushButton_4.clicked.connect(self.pushButton_4_clicked)    # 断开链接
        self.pushButton.clicked.connect(self.pushButton_clicked)        # 提交信息
        self.pushButton_6.clicked.connect(self.pushButton_6_clicked)    # 生产表增加行
        self.pushButton_7.clicked.connect(self.pushButton_7_clicked)    # 生产表删除行
        self.pushButton_9.clicked.connect(self.pushButton_9_clicked)    # 生产表增加列
        self.pushButton_8.clicked.connect(self.pushButton_8_clicked)    # 生产表删除列
        self.pushButton_13.clicked.connect(self.pushButton_13_clicked)  # 原料表增加行
        self.pushButton_10.clicked.connect(self.pushButton_10_clicked)  # 原料表删除行
        self.pushButton_11.clicked.connect(self.pushButton_11_clicked)  # 原料表增加列
        self.pushButton_12.clicked.connect(self.pushButton_12_clicked)  # 原料表删除列
        self.pushButton_14.clicked.connect(self.pushButton_14_clicked)  # 坯组编号合并按钮事件
        self.pushButton_15.clicked.connect(self.pushButton_15_clicked)  # 坯组编号分解按钮事件
        self.tableWidget.cellClicked.connect(self.on_cell_clicked_p)    # 点击获取当前行列数据
        self.tableWidget_2.cellClicked.connect(self.on_cell_clicked_m)  # 点击获取当前行列数据
        self.tableWidget.cellChanged.connect(self.on_cell_changed)      # 修改内容行列数据
        # ------------------------------B枪 按钮事件绑定--------------------------------
        self.pushButton_24.clicked.connect(self.pushButton_24_clicked)    # 生产表增加行
        self.pushButton_22.clicked.connect(self.pushButton_22_clicked)    # 生产表删除行
        self.pushButton_18.clicked.connect(self.pushButton_18_clicked)    # 生产表增加列
        self.pushButton_16.clicked.connect(self.pushButton_16_clicked)    # 生产表删除列
        self.pushButton_23.clicked.connect(self.pushButton_23_clicked)  # 原料表增加行
        self.pushButton_21.clicked.connect(self.pushButton_21_clicked)  # 原料表删除行
        self.pushButton_25.clicked.connect(self.pushButton_25_clicked)  # 原料表增加列
        self.pushButton_20.clicked.connect(self.pushButton_20_clicked)  # 原料表删除列
        self.pushButton_17.clicked.connect(self.pushButton_17_clicked)  # 坯组编号合并按钮事件
        self.pushButton_19.clicked.connect(self.pushButton_19_clicked)  # 坯组编号分解按钮事件
        self.tableWidget_3.cellClicked.connect(self.on_cell_clicked_p_b)    # 点击获取当前行列数据
        self.tableWidget_4.cellClicked.connect(self.on_cell_clicked_m_b)  # 点击获取当前行列数据
        self.tableWidget_3.cellChanged.connect(self.on_cell_changed_b)      # 修改内容行列数据

        # --------------------------多选按钮事件绑定-----------------------------
        self.radioButton_1.clicked.connect(self.pizu_number_update)  # A坯组数量 1
        self.radioButton_2.clicked.connect(self.pizu_number_update)  # A坯组数量 2
        self.radioButton_3.clicked.connect(self.pizu_number_update)  # A坯组数量 3
        self.radioButton_4.clicked.connect(self.pizu_number_update)  # A坯组数量 4
        self.radioButton_5.clicked.connect(self.pizu_number_update)  # A坯组数量 5
        self.radioButton_6.clicked.connect(self.pizu_number_update)  # A坯组数量 6

        self.radioButton_7.clicked.connect(self.bianhao_number_update)   # A边数数量 1
        self.radioButton_8.clicked.connect(self.bianhao_number_update)   # A边数数量 2
        self.radioButton_9.clicked.connect(self.bianhao_number_update)   # A边数数量 3
        self.radioButton_10.clicked.connect(self.bianhao_number_update)  # A边数数量 4
        self.radioButton_11.clicked.connect(self.bianhao_number_update)  # A边数数量 5
        self.radioButton_12.clicked.connect(self.bianhao_number_update)  # A边数数量 6

        self.radioButton_13.clicked.connect(self.pizu_number_update_b)  # A坯组数量 1
        self.radioButton_14.clicked.connect(self.pizu_number_update_b)  # A坯组数量 2
        self.radioButton_15.clicked.connect(self.pizu_number_update_b)  # A坯组数量 3
        self.radioButton_16.clicked.connect(self.pizu_number_update_b)  # A坯组数量 4
        self.radioButton_17.clicked.connect(self.pizu_number_update_b)  # A坯组数量 5
        self.radioButton_18.clicked.connect(self.pizu_number_update_b)  # A坯组数量 6

        self.radioButton_19.clicked.connect(self.bianhao_number_update_b)  # A边数数量 1
        self.radioButton_20.clicked.connect(self.bianhao_number_update_b)  # A边数数量 2
        self.radioButton_21.clicked.connect(self.bianhao_number_update_b)  # A边数数量 3
        self.radioButton_22.clicked.connect(self.bianhao_number_update_b)  # A边数数量 4
        self.radioButton_23.clicked.connect(self.bianhao_number_update_b)  # A边数数量 5
        self.radioButton_24.clicked.connect(self.bianhao_number_update_b)  # A边数数量 6

        # -----------------------------共用按钮------------------------------------
        self.pushButton_26.clicked.connect(self.pushButton_26_clicked)  # 重新运算按钮

        # 连接信号与槽
        self.Thread1.e_hl_a.connect(self.handle_e_hl_a)
        self.Thread1_B.e_hl_b.connect(self.handle_e_hl_b)
        self.Thread1.e_wfp_a.connect(self.handle_e_wfp_a)
        self.Thread1_B.e_wfp_b.connect(self.handle_e_wfp_b)
        self.Thread1.pizu_out_a.connect(self.pizu_out_dx_a)
        self.Thread1_B.pizu_out_b.connect(self.pizu_out_dx_b)
        self.Thread1.bianhao_out_a.connect(self.bianshu_out_dx_a)
        self.Thread1_B.bianhao_out_b.connect(self.bianshu_out_dx_b)

        # ------------------------------字符颜色设置-------------------------------
        self.label_21.setStyleSheet("color: red")
        self.label_25.setStyleSheet("color: red")
        self.label_22.setStyleSheet("color: green")
        self.label_26.setStyleSheet("color: green")
        self.label_23.setStyleSheet("color: blue")
        self.label_27.setStyleSheet("color: blue")
        self.label_24.setStyleSheet("color: purple")
        self.label_28.setStyleSheet("color: purple")
        # ------------------多线程开始-------------------
        self.Thread1.start()  # 页面显示自动开始A枪多线程
        self.Thread1_B.start()  # 页面显示自动开始B枪多线程

    # A 长宽错误界面提示
    def handle_e_hl_a(self):
        self.label_14.setStyleSheet("color: red")
        self.label_14.setText('A长宽错误，数据不正确，手动调整')

    # B 长宽错误界面提示
    def handle_e_hl_b(self):
        self.label_15.setStyleSheet("color: red")
        self.label_15.setText('B长宽错误，数据不正确，手动调整')

    # A 坯组数量输出
    @Slot(int)
    def pizu_out_dx_a(self, pizu_number):
        if pizu_number == 1:
            self.radioButton_1.setChecked(True)
        elif pizu_number == 2:
            self.radioButton_2.setChecked(True)
        elif pizu_number == 3:
            self.radioButton_3.setChecked(True)
        elif pizu_number == 4:
            self.radioButton_4.setChecked(True)
        elif pizu_number == 5:
            self.radioButton_5.setChecked(True)
        elif pizu_number == 6:
            self.radioButton_6.setChecked(True)

    # B 坯组数量输出
    @Slot(int)
    def pizu_out_dx_b(self, pizu_number):
        if pizu_number == 1:
            self.radioButton_13.setChecked(True)
        elif pizu_number == 2:
            self.radioButton_14.setChecked(True)
        elif pizu_number == 3:
            self.radioButton_15.setChecked(True)
        elif pizu_number == 4:
            self.radioButton_16.setChecked(True)
        elif pizu_number == 5:
            self.radioButton_17.setChecked(True)
        elif pizu_number == 6:
            self.radioButton_18.setChecked(True)

    # A 边数数量输出
    @Slot(int)
    def bianshu_out_dx_a(self, pizu_number):
        if pizu_number == 1:
            self.radioButton_7.setChecked(True)
        elif pizu_number == 2:
            self.radioButton_8.setChecked(True)
        elif pizu_number == 3:
            self.radioButton_9.setChecked(True)
        elif pizu_number == 4:
            self.radioButton_10.setChecked(True)
        elif pizu_number == 5:
            self.radioButton_11.setChecked(True)
        elif pizu_number == 6:
            self.radioButton_12.setChecked(True)

    # B 边数数量输出
    @Slot(int)
    def bianshu_out_dx_b(self, pizu_number):
        if pizu_number == 1:
            self.radioButton_19.setChecked(True)
        elif pizu_number == 2:
            self.radioButton_20.setChecked(True)
        elif pizu_number == 3:
            self.radioButton_21.setChecked(True)
        elif pizu_number == 4:
            self.radioButton_22.setChecked(True)
        elif pizu_number == 5:
            self.radioButton_23.setChecked(True)
        elif pizu_number == 6:
            self.radioButton_24.setChecked(True)

    # 修改后的临时坯组编号 A
    @Slot(str)
    def handle_e_wfp_a(self, str_wfp):
        # print(12345678)
        self.wfp_allocated_name_A.append(str_wfp)

    # 修改后的临时坯组编号 B
    @Slot(str)
    def handle_e_wfp_b(self, str_wfp):
        self.wfp_allocated_name_B.append(str_wfp)

    def thread_start(self):
        self.label_4.setStyleSheet("color: blue")
        self.label_4.setText('数据获取中')

    def thread_start_B(self):
        self.label_10.setStyleSheet("color: blue")
        self.label_10.setText('数据获取中')

    def thread_finished(self):
        # ---------------------将获取到的数据陈列在表格框中----------------------
        self.ColumnCount1 = 7                                              # 设置列数
        self.tableWidget.setRowCount(len(self.Thread1.results1))
        self.tableWidget.setColumnCount(self.ColumnCount1)
        self.tableWidget.setHorizontalHeaderLabels(horizontalheaderitem1)  # 设置列名称  production表
        for rows, resultrow in enumerate(self.Thread1.results1):                        # 对数据集合中的每行进行操作
            for cols, resultcol in enumerate(resultrow):
                if cols == 0:
                    checkbox = QCheckBox()
                    checkbox.stateChanged.connect(lambda state, r=rows: self.on_checkbox_toggled(state, r))  # 多选框事件绑定
                    self.tableWidget.setCellWidget(rows, 0, checkbox)                                        # 在第一列放置选择框
                item_a = QTableWidgetItem(str(resultcol))
                item_a.setTextAlignment(Qt.AlignCenter)               # 设置内容居中
                self.tableWidget.setItem(rows, cols + 1, item_a)      # 设置单元格内容
        self.hebing(self.tableWidget)                                 # 合并首列同类项
        # 设置列宽自动调整
        self.tableWidget.resizeColumnsToContents()                    # 设置自适应宽度

        self.ColumnCount2 = 8                                         # 设置列数
        self.tableWidget_2.setRowCount(len(self.Thread1.results2))
        self.tableWidget_2.setColumnCount(self.ColumnCount2)
        self.tableWidget_2.setHorizontalHeaderLabels(horizontalheaderitem2)  # 设置列名称  material表
        for rows, resultrow in enumerate(self.Thread1.results2):                          # 对数据集合中的每行进行操作
            for cols, resultcol in enumerate(resultrow):
                # print("行：%s，列：%s，内容：%s" % (rows, cols, resultcol))
                item_a = QTableWidgetItem(str(resultcol))
                item_a.setTextAlignment(Qt.AlignCenter)                      # 设置内容居中
                self.tableWidget_2.setItem(rows, cols, item_a)
        self.hebing1(self.tableWidget_2)                                     # 合并首列同类项
                                                                             # 设置列宽自动调整
        self.tableWidget_2.resizeColumnsToContents()                         # 设置自适应宽度
        # -----------------------读取数据库坐标信息，绘制在图表中---------------------------
        for pizu, xingxi in self.Thread1.pizu_change.items():  # 存储字典的信息归位
            chart = QChart()
            # chart.setAspectRatioMode(Qt.KeepAspectRatio)  # 保持宽高比
            self.cursor.execute(
                """SELECT
                    MAX(X坐标) AS max_x,
                    MIN(X坐标) AS min_x,
                    MAX(Y坐标) AS max_y,
                    MIN(Y坐标) AS min_y
                FROM
                    persons_A
                WHERE
                    坯组编号 = %s
                    """, pizu)
            # 计算实际数据范围
            xy_rend = self.cursor.fetchone()  # 获取查询到的最大值与最小值
            # print("x_min", xy_rend)    #, x_max, y_min, y_max)
            x_max = float(xy_rend[0])
            x_min = float(xy_rend[1])
            y_max = float(xy_rend[2])
            y_min = float(xy_rend[3])

            x_span = x_max - x_min
            y_span = y_max - y_min

            # 根据最大跨度同步范围
            max_span = max(x_span, y_span) + 60
            # print("max_span", max_span)
            print(x_min + (x_max - x_min - max_span)/2)
            print(x_min + (x_max - x_min + max_span)/2)
            # 创建自定义坐标轴
            # 设置显示范围
            axis_x = QValueAxis()
            axis_x.setRange((x_max + x_min - max_span)/2, (x_max + x_min + max_span)/2)  # 使X轴跨度与Y轴一致
            # print("axis_x", axis_x.max(), axis_x.min())
            axis_y = QValueAxis()
            axis_y.setRange((y_max + y_min - max_span)/2, (y_max + y_min + max_span)/2)
            # print("axis_y", axis_y.max(), axis_y.min())

            # 添加坐标轴到图表
            chart.addAxis(axis_x, Qt.AlignBottom)
            chart.addAxis(axis_y, Qt.AlignLeft)

            # 创建图表视图并设置到布局
            chart_view = QChartView(chart)
            for i in range(1, 5):
                # 获取该临时坯组编号的边号
                self.cursor.execute(
                    """SELECT
                        X坐标, Y坐标
                    FROM
                        persons_A
                    WHERE 边号 = %d
                    AND 坯组编号 = %s
                    """, (i, pizu))
                xy_r = self.cursor.fetchall()  # 获取查询到的最大值与最小值

                # print("xy_r", xy_r)
                series = QScatterSeries()
                # 禁用自动缩放
                chart.setAnimationOptions(QChart.NoAnimation)

                chart.addSeries(series)  # 将系列添加到图表
                for xy in list(xy_r):
                    series.append(float(xy[0]), float(xy[1]))  # 点位 (10,20)
                # 设置点位属性
                series.setColor(self.colors[i-1])  # 设置点位颜色
                series.setMarkerSize(4.0)  # 设置点位直径（单位：像素）
                series.setBorderColor(Qt.transparent)  # 隐藏边框

                series.attachAxis(axis_x)
                series.attachAxis(axis_y)

            # 隐藏图例
            chart.legend().setVisible(False)
            # 隐藏所有坐标轴和网格
            for axis in chart.axes():
                axis.setGridLineVisible(False)  # 隐藏网格线
                axis.setLabelsVisible(False)  # 隐藏坐标标签
                axis.setLineVisible(False)  # 隐藏轴线
            chart.setBackgroundVisible(False)
            chart.layout().setContentsMargins(0, 0, 0, 0)  # 去除边距
            chart.setTitle(xingxi["pizu"])  # 设置图表标题

            # chart_view.setMaximumSize(250, 400)
            chart_view.setFixedSize(210, 190)  # 1:1 比例
            self.verticalLayout.addWidget(chart_view)  # 将视图添加到布局

        self.label_4.setStyleSheet("color: green")
        self.label_4.setText('数据识别生成成功')

    def thread_finished_B(self):
        # ---------------------将获取到的数据陈列在表格框中----------------------
        self.ColumnCount1_B = 7  # 设置列数
        self.tableWidget_3.setRowCount(len(self.Thread1_B.results1))
        self.tableWidget_3.setColumnCount(self.ColumnCount1_B)
        self.tableWidget_3.setHorizontalHeaderLabels(horizontalheaderitem1)  # 设置列名称  production表
        for rows, resultrow in enumerate(self.Thread1_B.results1):                        # 对数据集合中的每行进行操作
            for cols, resultcol in enumerate(resultrow):
                if cols == 0:
                    checkbox = QCheckBox()
                    checkbox.stateChanged.connect(lambda state, r=rows: self.on_checkbox_toggled_B(state, r))  # 多选框事件绑定
                    self.tableWidget_3.setCellWidget(rows, 0, checkbox)                                        # 在第一列放置选择框
                item_a = QTableWidgetItem(str(resultcol))
                item_a.setTextAlignment(Qt.AlignCenter)                 # 设置内容居中
                self.tableWidget_3.setItem(rows, cols + 1, item_a)      # 设置单元格内容
        self.hebing(self.tableWidget_3)                                 # 合并首列同类项
        # 设置列宽自动调整
        self.tableWidget_3.resizeColumnsToContents()                    # 设置自适应宽度

        self.ColumnCount2 = 8                                           # 设置列数
        self.tableWidget_4.setRowCount(len(self.Thread1_B.results2))
        self.tableWidget_4.setColumnCount(self.ColumnCount2)
        self.tableWidget_4.setHorizontalHeaderLabels(horizontalheaderitem2)  # 设置列名称  material表
        for rows, resultrow in enumerate(self.Thread1_B.results2):                          # 对数据集合中的每行进行操作
            for cols, resultcol in enumerate(resultrow):
                # print("行：%s，列：%s，内容：%s" % (rows, cols, resultcol))
                item_a = QTableWidgetItem(str(resultcol))
                item_a.setTextAlignment(Qt.AlignCenter)                      # 设置内容居中
                self.tableWidget_4.setItem(rows, cols, item_a)
        self.hebing1(self.tableWidget_4)                                     # 合并首列同类项
                                                                             # 设置列宽自动调整
        self.tableWidget_4.resizeColumnsToContents()                         # 设置自适应宽度
        # -----------------------读取数据库坐标信息，绘制在图表中---------------------------
        for pizu, xingxi in self.Thread1_B.pizu_change.items():  # 存储字典的信息归位
            chart = QChart()
            # chart.setAspectRatioMode(Qt.KeepAspectRatio)  # 保持宽高比
            self.cursor.execute(
                """SELECT
                    MAX(X坐标) AS max_x,
                    MIN(X坐标) AS min_x,
                    MAX(Y坐标) AS max_y,
                    MIN(Y坐标) AS min_y
                FROM
                    persons_B
                WHERE
                    坯组编号 = %s
                    """, pizu)
            # 计算实际数据范围
            xy_rend = self.cursor.fetchone()  # 获取查询到的最大值与最小值
            # print("x_min", xy_rend)  # , x_max, y_min, y_max)
            x_max = float(xy_rend[0])
            x_min = float(xy_rend[1])
            y_max = float(xy_rend[2])
            y_min = float(xy_rend[3])

            x_span = x_max - x_min
            y_span = y_max - y_min

            # 根据最大跨度同步范围
            max_span = max(x_span, y_span) + 60
            # print("max_span", max_span)
            # print(x_min + (x_max - x_min - max_span) / 2)
            # print(x_min + (x_max - x_min + max_span) / 2)
            # 创建自定义坐标轴
            # 设置显示范围
            axis_x = QValueAxis()
            axis_x.setRange((x_max + x_min - max_span) / 2, (x_max + x_min + max_span) / 2)  # 使X轴跨度与Y轴一致
            # print("axis_x", axis_x.max(), axis_x.min())
            axis_y = QValueAxis()
            axis_y.setRange((y_max + y_min - max_span) / 2, (y_max + y_min + max_span) / 2)
            # print("axis_y", axis_y.max(), axis_y.min())

            # 添加坐标轴到图表
            chart.addAxis(axis_x, Qt.AlignBottom)
            chart.addAxis(axis_y, Qt.AlignLeft)

            # 创建图表视图并设置到布局
            chart_view = QChartView(chart)
            for i in range(1, 5):
                # 获取该临时坯组编号的边号
                self.cursor.execute(
                    """SELECT
                        X坐标, Y坐标
                    FROM
                        persons_B
                    WHERE 边号 = %d
                    AND 坯组编号 = %s
                    """, (i, pizu))
                xy_r = self.cursor.fetchall()  # 获取查询到的最大值与最小值

                # print("xy_r", xy_r)
                series = QScatterSeries()
                # 禁用自动缩放
                chart.setAnimationOptions(QChart.NoAnimation)

                chart.addSeries(series)  # 将系列添加到图表
                for xy in list(xy_r):
                    series.append(float(xy[0]), float(xy[1]))  # 点位 (10,20)
                # 设置点位属性
                series.setColor(self.colors[i - 1])  # 设置点位颜色
                series.setMarkerSize(4.0)  # 设置点位直径（单位：像素）
                series.setBorderColor(Qt.transparent)  # 隐藏边框

                series.attachAxis(axis_x)
                series.attachAxis(axis_y)

            # 隐藏图例
            chart.legend().setVisible(False)
            # 隐藏所有坐标轴和网格
            for axis in chart.axes():
                axis.setGridLineVisible(False)  # 隐藏网格线
                axis.setLabelsVisible(False)  # 隐藏坐标标签
                axis.setLineVisible(False)  # 隐藏轴线
            chart.setBackgroundVisible(False)
            chart.layout().setContentsMargins(0, 0, 0, 0)  # 去除边距
            chart.setTitle(xingxi["pizu"])  # 设置图表标题

            # chart_view.setMaximumSize(250, 400)
            chart_view.setFixedSize(210, 190)  # 1:1 比例
            self.verticalLayout_2.addWidget(chart_view)  # 将视图添加到布局
        self.label_10.setStyleSheet("color: green")
        self.label_10.setText('数据识别生成成功')

    def hebing(self, tablewg):  # 用于第一个表格的表格合并——生产表
        types = {}  # 合并同类型单元格
        for row in range(tablewg.rowCount()):
            type_item = tablewg.item(row, 1)
            if type_item is not None:
                type_text = type_item.text()
                if type_text not in types:
                    types[type_text] = []
                types[type_text].append(row)
        # 合并相邻的单元格
        for type_text, rows in types.items():
            merged_rows = []  # 用于存储合并的行
            start_row = None  # 记住合并的起始行

            for i in range(len(rows)):
                current_row = rows[i]
                # 如果是首个元素或当前行与前一行不相邻
                if start_row is None:
                    start_row = current_row
                elif current_row != rows[i - 1] + 1:
                    # 如果不相邻，合并之前的行
                    if start_row is not None and i > 1:
                        row_span = i  # 计算行跨度
                        tablewg.setSpan(start_row, 0, row_span, 1)
                        tablewg.setSpan(start_row, 1, row_span, 1)
                    # 更新起始行
                    start_row = current_row

            # 最后一次合并
            if start_row is not None and len(rows) > 1:
                row_span = len(rows) - (rows.index(start_row) + 1)
                if row_span > 0:
                    tablewg.setSpan(start_row, 0, row_span + 1, 1)
                    tablewg.setSpan(start_row, 1, row_span + 1, 1)

    def hebing1(self, tablewg):  # 用于第二个表格的表格合并——材料表
        types = {}  # 合并同类型单元格
        for row in range(tablewg.rowCount()):
            type_item = tablewg.item(row, 0)
            if type_item is not None:
                type_text = type_item.text()
                if type_text not in types:
                    types[type_text] = []
                types[type_text].append(row)
        # 合并相邻的单元格
        for type_text, rows in types.items():
            merged_rows = []  # 用于存储合并的行
            start_row = None  # 记住合并的起始行

            for i in range(len(rows)):
                current_row = rows[i]
                # 如果是首个元素或当前行与前一行不相邻
                if start_row is None:
                    start_row = current_row
                elif current_row != rows[i - 1] + 1:
                    # 如果不相邻，合并之前的行
                    if start_row is not None and i > 1:
                        row_span = i  # 计算行跨度
                        tablewg.setSpan(start_row, 0, row_span, 1)
                    # 更新起始行
                    start_row = current_row
            # 最后一次合并
            if start_row is not None and len(rows) > 1:
                row_span = len(rows) - (rows.index(start_row) + 1)
                if row_span > 0:
                    tablewg.setSpan(start_row, 0, row_span + 1, 1)

    def on_checkbox_toggled(self, state, row):
        """   选择框状态变化时的处理函数   """
        global duoxuan
        item_name = self.tableWidget.item(row, 1).text()  # 获取对应行的名称
        if state == 2:  # 2 表示选中状态
            duoxuan.append(item_name)
            # print(item_name)
        else:
            duoxuan.remove(item_name)

    def on_checkbox_toggled_B(self, state, row):
        """   选择框状态变化时的处理函数   """
        global duoxuan
        item_name = self.tableWidget_3.item(row, 1).text()  # 获取对应行的名称
        if state == 2:  # 2 表示选中状态
            duoxuan.append(item_name)
            # print(item_name)
        else:
            duoxuan.remove(item_name)

    # 坯组数数量设置产线，规律，耗材，维护，
    def pizu_number_update(self):
        if self.radioButton_1.isChecked():
            self.Thread1.pizu_number = 1
        elif self.radioButton_2.isChecked():
            self.Thread1.pizu_number = 2
        elif self.radioButton_3.isChecked():
            self.Thread1.pizu_number = 3
        elif self.radioButton_4.isChecked():
            self.Thread1.pizu_number = 4
        elif self.radioButton_5.isChecked():
            self.Thread1.pizu_number = 5
        elif self.radioButton_6.isChecked():
            self.Thread1.pizu_number = 6

    def pizu_number_update_b(self):
        if self.radioButton_13.isChecked():
            self.Thread1_B.pizu_number = 1
        elif self.radioButton_14.isChecked():
            self.Thread1_B.pizu_number = 2
        elif self.radioButton_15.isChecked():
            self.Thread1_B.pizu_number = 3
        elif self.radioButton_16.isChecked():
            self.Thread1_B.pizu_number = 4
        elif self.radioButton_17.isChecked():
            self.Thread1_B.pizu_number = 5
        elif self.radioButton_18.isChecked():
            self.Thread1_B.pizu_number = 6

    # 边数数量设置
    def bianhao_number_update(self):
        if self.radioButton_7.isChecked():
            self.Thread1.bian_number = 1
        elif self.radioButton_8.isChecked():
            self.Thread1.bian_number = 2
        elif self.radioButton_9.isChecked():
            self.Thread1.bian_number = 3
        elif self.radioButton_10.isChecked():
            self.Thread1.bian_number = 4
        elif self.radioButton_11.isChecked():
            self.Thread1.bian_number = 5
        elif self.radioButton_12.isChecked():
            self.Thread1.bian_number = 6

    def bianhao_number_update_b(self):
        if self.radioButton_19.isChecked():
            self.Thread1_B.bian_number = 1
        elif self.radioButton_20.isChecked():
            self.Thread1_B.bian_number = 2
        elif self.radioButton_21.isChecked():
            self.Thread1_B.bian_number = 3
        elif self.radioButton_22.isChecked():
            self.Thread1_B.bian_number = 4
        elif self.radioButton_23.isChecked():
            self.Thread1_B.bian_number = 5
        elif self.radioButton_24.isChecked():
            self.Thread1_B.bian_number = 6
    def pushButton_clicked(self):  # 将信息提交至数据库
        bianhao = ["1", "2", "3", "4"]
        for pizu, xingxi in self.Thread1.pizu_change.items():  # 存储字典的信息归位
            if pizu == xingxi["pizu"]:
                continue
            else:
                for i in bianhao:  # 先改边号
                    self.cursor.execute("""
                                        UPDATE persons_A
                                        SET 边号 = %d
                                        WHERE 边号 = %d
                                        AND 坯组编号 = %s
                                        """, (int(xingxi[i]), int(i), pizu))
                    self.conn.commit()  # 提交事务
                # 再改坯组编号
                self.cursor.execute("""
                                UPDATE persons_A
                                SET 坯组编号 = %s
                                WHERE 坯组编号 = %s
                                """, (xingxi["pizu"], pizu))
                self.conn.commit()  # 提交事务
        # 第三步：在提交时根据修改信息对数据库进行操作   A
        try:
            for i in range(self.tableWidget.rowCount()):
                sql_insert_p = "INSERT INTO production (坯组编号, 边号, 操作员, 填写时间, 开始时间, 结束时间) VALUES (%s, %d, %s, %s, %s, %s)"
                # 执行数据库，链接sqlserver，插入语句
                self.cursor.execute(sql_insert_p, (
                    self.tableWidget.item(i, 1).text(), self.tableWidget.item(i, 2).text(),
                    self.tableWidget.item(i, 3).text(),
                    self.tableWidget.item(i, 4).text(), self.tableWidget.item(i, 5).text(),
                    self.tableWidget.item(i, 6).text()))
            for i in range(self.tableWidget_2.rowCount()):
                sql_insert_m = "INSERT INTO material (坯组编号, 板坯编号, 板坯顺序, 原料材质, 原料长度, 原料宽度, 原料厚度, 备注) VALUES (%s, %s, %d, %s, %d, %d, %d, %s)"
                # 执行数据库，链接sqlserver，["坯组编号", "板坯编号", "板坯顺序", "原料材质", "原料长度", "原料宽度", "原料厚度", "备注"]
                self.cursor.execute(sql_insert_m, (
                    self.tableWidget_2.item(i, 0).text(), self.tableWidget_2.item(i, 1).text(),
                    self.tableWidget_2.item(i, 2).text(), self.tableWidget_2.item(i, 3).text(),
                    self.tableWidget_2.item(i, 4).text(), self.tableWidget_2.item(i, 5).text(),
                    self.tableWidget_2.item(i, 6).text(), self.tableWidget_2.item(i, 7).text()))
            self.label_4.setStyleSheet("color: blue")
            self.label_4.setText('提交成功')
        except:
            self.label_4.setStyleSheet("color: red")
            self.label_4.setText('提交失败')

        for pizu, xingxi in self.Thread1_B.pizu_change.items():  # B存储字典的信息归位
            if pizu == xingxi["pizu"]:
                continue
            else:
                for i in bianhao:  # 先改边号
                    self.cursor.execute("""
                                                UPDATE persons_B
                                                SET 边号 = %d
                                                WHERE 边号 = %d
                                                AND 坯组编号 = %s
                                                """, (int(xingxi[i]), int(i), pizu))
                    self.conn.commit()  # 提交事务
                # 再改坯组编号
                self.cursor.execute("""
                                        UPDATE persons_B
                                        SET 坯组编号 = %s
                                        WHERE 坯组编号 = %s
                                        """, (xingxi["pizu"], pizu))
                self.conn.commit()  # 提交事务
        # 第三步：在提交时根据修改信息对数据库进行操作  B
        try:
            for i in range(self.tableWidget_3.rowCount()):
                sql_insert_p = "INSERT INTO production (坯组编号, 边号, 操作员, 填写时间, 开始时间, 结束时间) VALUES (%s, %d, %s, %s, %s, %s)"
                # 执行数据库，链接sqlserver，插入语句
                self.cursor.execute(sql_insert_p, (
                    self.tableWidget_3.item(i, 1).text(), self.tableWidget_3.item(i, 2).text(),
                    self.tableWidget_3.item(i, 3).text(),
                    self.tableWidget_3.item(i, 4).text(), self.tableWidget_3.item(i, 5).text(),
                    self.tableWidget_3.item(i, 6).text()))
            for i in range(self.tableWidget_4.rowCount()):
                sql_insert_m = "INSERT INTO material (坯组编号, 板坯编号, 板坯顺序, 原料材质, 原料长度, 原料宽度, 原料厚度, 备注) VALUES (%s, %s, %d, %s, %d, %d, %d, %s)"
                # 执行数据库，链接sqlserver，["坯组编号", "板坯编号", "板坯顺序", "原料材质", "原料长度", "原料宽度", "原料厚度", "备注"]
                self.cursor.execute(sql_insert_m, (
                    self.tableWidget_4.item(i, 0).text(), self.tableWidget_4.item(i, 1).text(),
                    self.tableWidget_4.item(i, 2).text(), self.tableWidget_4.item(i, 3).text(),
                    self.tableWidget_4.item(i, 4).text(), self.tableWidget_4.item(i, 5).text(),
                    self.tableWidget_4.item(i, 6).text(), self.tableWidget_4.item(i, 7).text()))
            self.label_10.setStyleSheet("color: blue")
            self.label_10.setText('提交成功')
        except:
            self.label_10.setStyleSheet("color: red")
            self.label_10.setText('提交失败')

    # def pushButton_4_clicked(self):
    #     self.conn.close()
    #     self.cursor.close()
    #     self.label.setStyleSheet("color: red")
    #     self.label.setText('数据库断开')
    # def pushButton_5_clicked(self):
    #     from ..main import servermy, portmy, usermy, passwordmy, databasemy
    #     self.conn = pymssql.connect(server=servermy, port=portmy, user=usermy, password=passwordmy, database=databasemy,
    #                                 charset='utf8')
    #     self.label.setStyleSheet("color: green")
    #     self.label.setText('数据库链接成功')
    #     self.cursor = self.conn.cursor(as_dict=True)
    #     self.conn.autocommit(True)  # 设置是否自动提交事务

    def on_cell_clicked_p(self, row, column):    # A枪行列数据获取动作
        # print("11111111"+row, column, self.tableWidget.item(row, column).text())
        global clck_v
        self.tableWidget.rows = row
        self.tableWidget.columns = column
        clck_v = self.tableWidget.item(row, column).text()

    def on_cell_clicked_p_b(self, row, column):  # B枪行列数据获取动作
        # print("11111111"+row, column, self.tableWidget.item(row, column).text())
        global clck_v
        self.tableWidget_3.rows = row
        self.tableWidget_3.columns = column
        clck_v = self.tableWidget_3.item(row, column).text()

    def on_cell_clicked_m(self, row, column):  # A 行列数据获取动作
        self.tableWidget_2.rows = row
        self.tableWidget_2.columns = column

    def on_cell_clicked_m_b(self, row, column):  # B 行列数据获取动作
        self.tableWidget_4.rows = row
        self.tableWidget_4.columns = column

    def on_cell_changed(self, row, col):       # A 生产表格修改事件
        new_value = self.tableWidget.item(row, col).text()
        if self.tableWidget.rows is None or self.tableWidget.columns is None:
            return
        else:
            if self.tableWidget.rows == row and self.tableWidget.columns == col:
                self.cursor.execute(
                    """SELECT
                         坯组编号
                    FROM
                        persons
                    WHERE
                        坯组编号 = %s
                        """, new_value)
                results = self.cursor.fetchall()  # 获取查询到的所有信息
                if results:
                    print("数据库内已有此数据，请确认")
                    self.label_4.setStyleSheet("color: red")
                    self.label_4.setText('数据库内已有此数据，请确认')
                # self.Thread1.pizu_change
                # print(row, col, clck_v, self.tableWidget.item(row, col).text())
                for rows in range(self.tableWidget.rowCount()):  # 修改表一：生产表内容
                    item_name = self.tableWidget.item(rows, 1).text()  # 获取坯组编号的名称
                    if item_name == clck_v:
                        # print("修改坯组编号%s-为%s", (item_name, new_value))
                        item = QTableWidgetItem(new_value)
                        item.setTextAlignment(Qt.AlignCenter)  # 设置内容居中
                        self.tableWidget.setItem(rows, 1, item)  # 设置坯组编号单元格内容
                        # 执行更新操作
                for rows in range(self.tableWidget_2.rowCount()):  # 修改表二：原料表内容
                    item_name = self.tableWidget_2.item(rows, 0).text()  # 获取坯组编号的名称
                    if item_name == clck_v:
                        item = QTableWidgetItem(new_value)
                        item.setTextAlignment(Qt.AlignCenter)  # 设置内容居中
                        self.tableWidget_2.setItem(rows, 0, item)  # 设置坯组编号单元格内容
                for key, value in self.Thread1.pizu_change.items():
                    if value["pizu"] == clck_v:
                        value["pizu"] = self.tableWidget.item(row, col).text()
                self.hebing(self.tableWidget)  # 合并首列同类项
                self.hebing1(self.tableWidget_2)  # 合并首列同类项
                self.tableWidget.rows = None
                self.tableWidget.columns = None

    def on_cell_changed_b(self, row, col):       # B 生产表格修改事件
        new_value = self.tableWidget_3.item(row, col).text()
        if self.tableWidget_3.rows is None or self.tableWidget_3.columns is None:
            return
        else:
            if self.tableWidget_3.rows == row and self.tableWidget_3.columns == col:
                self.cursor.execute(
                    """SELECT
                         坯组编号
                    FROM
                        persons
                    WHERE
                        坯组编号 = %s
                        """, new_value)
                results = self.cursor.fetchall()  # 获取查询到的所有信息
                if results:
                    print("数据库内已有此数据，请确认")
                    self.label_4.setStyleSheet("color: red")
                    self.label_4.setText('数据库内已有此数据，请确认')
                # global pizu_change
                # print(row, col, clck_v, self.tableWidget.item(row, col).text())
                for rows in range(self.tableWidget_3.rowCount()):  # 修改表一：生产表内容
                    item_name = self.tableWidget_3.item(rows, 1).text()  # 获取坯组编号的名称
                    if item_name == clck_v:
                        # print("修改坯组编号%s-为%s", (item_name, new_value))
                        item = QTableWidgetItem(new_value)
                        item.setTextAlignment(Qt.AlignCenter)  # 设置内容居中
                        self.tableWidget_3.setItem(rows, 1, item)  # 设置坯组编号单元格内容
                        # 执行更新操作
                for rows in range(self.tableWidget_4.rowCount()):  # 修改表二：原料表内容
                    item_name = self.tableWidget_4.item(rows, 0).text()  # 获取坯组编号的名称
                    if item_name == clck_v:
                        item = QTableWidgetItem(new_value)
                        item.setTextAlignment(Qt.AlignCenter)  # 设置内容居中
                        self.tableWidget_4.setItem(rows, 0, item)  # 设置坯组编号单元格内容
                for key, value in self.Thread1_B.pizu_change.items():
                    if value["pizu"] == clck_v:
                        value["pizu"] = self.tableWidget_3.item(row, col).text()
                self.hebing(self.tableWidget_3)  # 合并首列同类项
                self.hebing1(self.tableWidget_4)  # 合并首列同类项
                self.tableWidget_3.rows = None
                self.tableWidget_3.columns = None

    def pushButton_6_clicked(self):   # A 新增行
        row = self.tableWidget.rows
        self.tableWidget.insertRow(row)

    def pushButton_24_clicked(self):  # B 新增行
        row = self.tableWidget_3.rows
        self.tableWidget_3.insertRow(row)

    def pushButton_7_clicked(self):  # A 删除行
        row = self.tableWidget.rows
        self.tableWidget.removeRow(row)

    def pushButton_22_clicked(self):  # B 删除行
        row = self.tableWidget_3.rows
        self.tableWidget_3.removeRow(row)

    def pushButton_9_clicked(self):  # A 新增列
        column = self.tableWidget.columns
        self.tableWidget.insertColumn(column)

    def pushButton_18_clicked(self):  # B 新增列
        column = self.tableWidget_3.columns
        self.tableWidget_3.insertColumn(column)

    def pushButton_8_clicked(self):  # A 删除列
        column = self.tableWidget.columns
        self.tableWidget.removeColumn(column)

    def pushButton_16_clicked(self):  # B 删除列
        column = self.tableWidget_3.columns
        self.tableWidget_3.removeColumn(column)

    def pushButton_13_clicked(self):  # A 原料表增加行
        row = self.tableWidget_2.rows
        self.tableWidget_2.insertRow(row)

    def pushButton_23_clicked(self):  # B 原料表增加行
        row = self.tableWidget_4.rows
        self.tableWidget_4.insertRow(row)

    def pushButton_10_clicked(self):  # A 原料表删除行
        row = self.tableWidget_2.rows
        self.tableWidget_2.removeRow(row)

    def pushButton_21_clicked(self):  # B 原料表删除行
        row = self.tableWidget_4.rows
        self.tableWidget_4.removeRow(row)

    def pushButton_11_clicked(self):   # A 原料表增加列
        column = self.tableWidget_2.columns
        self.tableWidget_2.insertColumn(column)

    def pushButton_25_clicked(self):   # B 原料表增加列
        column = self.tableWidget_4.columns
        self.tableWidget_4.insertColumn(column)

    def pushButton_12_clicked(self):   # A 原料表删除列
        column = self.tableWidget_2.columns
        self.tableWidget_2.removeColumn(column)

    def pushButton_20_clicked(self):   # B 原料表删除列
        column = self.tableWidget_4.columns
        self.tableWidget_4.removeColumn(column)

    def pushButton_14_clicked(self):  # A 坯组编号合并按钮事件
        global duoxuan                # 多选选中的-临时键名称
        # print(duoxuan)
        duoxuan_zs = {}
        # 合并坯组编号第一步：根据 duoxuan 数组中的内容取最小选项设置
        # 提取数字部分并找到最小值
        for key in duoxuan:
            for key1, view in self.Thread1.pizu_change.items():
                if view["pizu"] == key:
                    duoxuan_zs[key] = key1
        # print(duoxuan_zs)
        # 使用 sorted() 函数进行排序
        duoxuan = sorted(duoxuan)
        min_value = duoxuan[0]  # 最小值索引
        # print("最小值：%s", min_value)
        # 找到最小坯组编号中的边号最大值
        results = self.Thread1.pizu_change[duoxuan_zs[min_value]]["max_bian"]  # 字典中的边数最大值
        # 改变表格中内容
        for i, view in enumerate(duoxuan):
            if i == 0:
                for rows in range(self.tableWidget.rowCount()):  # 重新布置多选框
                    checkbox = QCheckBox()
                    checkbox.stateChanged.connect(lambda state, r=rows: self.on_checkbox_toggled(state, r))  # 多选框事件绑定
                    self.tableWidget.setCellWidget(rows, 0, checkbox)  # 在第一列放置选择框
                # print("成功跳过最小值部分%s", view)
                continue
            # print("此次修改%s", view)
            for rows in range(self.tableWidget.rowCount()):        # 修改表一：生产表内容
                item_name = self.tableWidget.item(rows, 1).text()  # 获取坯组编号的名称
                item_bian = self.tableWidget.item(rows, 2).text()  # 获取边号的名称
                if item_name == view:
                    duoxuan_zs[item_name]
                    # print("修改坯组编号%s-为%s", (item_name, min_value))
                    item = QTableWidgetItem(min_value)
                    item.setTextAlignment(Qt.AlignCenter)    # 设置内容居中
                    self.tableWidget.setItem(rows, 1, item)  # 设置坯组编号单元格内容
                    results = results + 1
                    item1 = QTableWidgetItem(str(results))
                    item1.setTextAlignment(Qt.AlignCenter)    # 设置内容居中
                    self.tableWidget.setItem(rows, 2, item1)  # 设置边号单元格内容
                    self.Thread1.pizu_change[duoxuan_zs[view]][item_bian] = str(results)  # 在字典中修改对应边号
                    # print(self.Thread1.pizu_change)
                    # 执行更新操作
            for rows in range(self.tableWidget_2.rowCount()):  # 修改表二：原料表内容
                item_name = self.tableWidget_2.item(rows, 0).text()  # 获取坯组编号的名称
                if item_name == view:
                    item = QTableWidgetItem(min_value)
                    item.setTextAlignment(Qt.AlignCenter)  # 设置内容居中
                    self.tableWidget_2.setItem(rows, 0, item)  # 设置坯组编号单元格内容
            for pizu, xingxi in self.Thread1.pizu_change.items():
                if xingxi["pizu"] == view:
                    xingxi["max_bian"] = 0
                    xingxi["pizu"] = min_value
        self.Thread1.pizu_change[duoxuan_zs[min_value]]["max_bian"] = results

        duoxuan.clear()
        results = 0
        # 第二步：之后的编号根据合并后的内容递增修改
        # 获取当前表格中存在的坯组编号
        # 创建新的列表
        new_data = []
        # 提取当前最小值前缀和数字部分
        prefix = min_value[:-2]  # 提取前缀（去掉尾部的两位数字）
        number = int(min_value[-2:])  # 提取尾部的数字并转换为整数
        # print("前缀：", prefix, "后缀", number)
        for pizu, xingxi in self.Thread1.pizu_change.items():
            # print("xingxi:",xingxi)
            if int(xingxi["pizu"][-2:]) > number:
                # print(pizu, xingxi)
                new_data.append(xingxi["pizu"])
        unique_labels = np.unique(new_data)  # 去重计算
        # print("unique_labels:", unique_labels)
        new_data.clear()  # 去除之前的数据
        # 使用一个循环生成连续的数字，并添加到新列表
        for i in range(len(unique_labels)):  # 假设需要生成两个连续数字
            new_item = prefix + f"{number + i + 1:02d}"
            new_data.append(new_item)
        new_data = np.array(new_data)  # 列表转np数组
        # 使用布尔索引去除位置与内容相同的项
        # mask = new_data != unique_labels
        # new_data = new_data[mask]
        # unique_labels = unique_labels[mask]
        # print("新修改：%s", new_data)
        # print("旧值：%s", unique_labels)
        for item in range(len(unique_labels)):
            for pizu, xingxi in self.Thread1.pizu_change.items():                 # 修改字典中的信息
                if xingxi["pizu"] == unique_labels[item]:
                    xingxi["pizu"] = str(new_data[item])
            for rows in range(self.tableWidget.rowCount()):
                item_name = self.tableWidget.item(rows, 1).text()    # 获取坯组编号的名称
                if item_name == unique_labels[item]:
                    item1 = QTableWidgetItem(str(new_data[item]))
                    self.tableWidget.setItem(rows, 1, item1)         # 设置坯组编号单元格内容
            for rows in range(self.tableWidget_2.rowCount()):
                item_name = self.tableWidget_2.item(rows, 0).text()  # 获取坯组编号的名称
                if item_name == unique_labels[item]:
                    item1 = QTableWidgetItem(str(new_data[item]))
                    self.tableWidget_2.setItem(rows, 0, item1)       # 设置坯组编号单元格内容
        self.hebing(self.tableWidget)        # 合并首列同类项
        self.hebing1(self.tableWidget_2)     # 合并首列同类项

    def pushButton_17_clicked(self):  # B 坯组编号合并按钮事件
        global duoxuan                # 多选选中的-临时键名称
        # print(duoxuan)
        duoxuan_zs = {}
        # 合并坯组编号第一步：根据 duoxuan 数组中的内容取最小选项设置
        # 提取数字部分并找到最小值
        for key in duoxuan:
            for key1, view in self.Thread1_B.pizu_change.items():
                if view["pizu"] == key:
                    duoxuan_zs[key] = key1
        # print(duoxuan_zs)
        # 使用 sorted() 函数进行排序
        duoxuan = sorted(duoxuan)
        min_value = duoxuan[0]  # 最小值索引
        # print("最小值：%s", min_value)
        # 找到最小坯组编号中的边号最大值
        results = self.Thread1_B.pizu_change[duoxuan_zs[min_value]]["max_bian"]  # 字典中的边数最大值
        # 改变表格中内容
        for i, view in enumerate(duoxuan):
            if i == 0:
                for rows in range(self.tableWidget_3.rowCount()):  # 重新布置多选框
                    checkbox = QCheckBox()
                    checkbox.stateChanged.connect(lambda state, r=rows: self.on_checkbox_toggled_B(state, r))  # 多选框事件绑定
                    self.tableWidget_3.setCellWidget(rows, 0, checkbox)  # 在第一列放置选择框
                # print("成功跳过最小值部分%s", view)
                continue
            # print("此次修改%s", view)
            for rows in range(self.tableWidget_3.rowCount()):        # 修改表一：生产表内容
                item_name = self.tableWidget_3.item(rows, 1).text()  # 获取坯组编号的名称
                item_bian = self.tableWidget_3.item(rows, 2).text()  # 获取边号的名称
                if item_name == view:
                    duoxuan_zs[item_name]
                    # print("修改坯组编号%s-为%s", (item_name, min_value))
                    item = QTableWidgetItem(min_value)
                    item.setTextAlignment(Qt.AlignCenter)    # 设置内容居中
                    self.tableWidget_3.setItem(rows, 1, item)  # 设置坯组编号单元格内容
                    results = results + 1
                    item1 = QTableWidgetItem(str(results))
                    item1.setTextAlignment(Qt.AlignCenter)    # 设置内容居中
                    self.tableWidget_3.setItem(rows, 2, item1)  # 设置边号单元格内容
                    self.Thread1_B.pizu_change[duoxuan_zs[view]][item_bian] = str(results)  # 在字典中修改对应边号
                    # print(self.Thread1_B.pizu_change)
                    # 执行更新操作
            for rows in range(self.tableWidget_4.rowCount()):  # 修改表二：原料表内容
                item_name = self.tableWidget_4.item(rows, 0).text()  # 获取坯组编号的名称
                if item_name == view:
                    item = QTableWidgetItem(min_value)
                    item.setTextAlignment(Qt.AlignCenter)  # 设置内容居中
                    self.tableWidget_4.setItem(rows, 0, item)  # 设置坯组编号单元格内容
            for pizu, xingxi in self.Thread1_B.pizu_change.items():
                if xingxi["pizu"] == view:
                    xingxi["max_bian"] = 0
                    xingxi["pizu"] = min_value
        self.Thread1_B.pizu_change[duoxuan_zs[min_value]]["max_bian"] = results

        duoxuan.clear()
        results = 0
        # 第二步：之后的编号根据合并后的内容递增修改
        # 获取当前表格中存在的坯组编号
        # 创建新的列表
        new_data = []
        # 提取当前最小值前缀和数字部分
        prefix = min_value[:-2]  # 提取前缀（去掉尾部的两位数字）
        number = int(min_value[-2:])  # 提取尾部的数字并转换为整数
        # print("前缀：", prefix, "后缀", number)
        for pizu, xingxi in self.Thread1_B.pizu_change.items():
            # print("xingxi:",xingxi)
            if int(xingxi["pizu"][-2:]) > number:
                # print(pizu, xingxi)
                new_data.append(xingxi["pizu"])
        unique_labels = np.unique(new_data)  # 去重计算
        # print("unique_labels:", unique_labels)
        new_data.clear()  # 去除之前的数据
        # 使用一个循环生成连续的数字，并添加到新列表
        for i in range(len(unique_labels)):  # 假设需要生成两个连续数字
            new_item = prefix + f"{number + i + 1:02d}"
            new_data.append(new_item)
        new_data = np.array(new_data)  # 列表转np数组
        # 使用布尔索引去除位置与内容相同的项
        # mask = new_data != unique_labels
        # new_data = new_data[mask]
        # unique_labels = unique_labels[mask]
        # print("新修改：%s", new_data)
        # print("旧值：%s", unique_labels)
        for item in range(len(unique_labels)):
            for pizu, xingxi in self.Thread1_B.pizu_change.items():                 # 修改字典中的信息
                if xingxi["pizu"] == unique_labels[item]:
                    xingxi["pizu"] = str(new_data[item])
            for rows in range(self.tableWidget_3.rowCount()):
                item_name = self.tableWidget_3.item(rows, 1).text()    # 获取坯组编号的名称
                if item_name == unique_labels[item]:
                    item1 = QTableWidgetItem(str(new_data[item]))
                    self.tableWidget_3.setItem(rows, 1, item1)         # 设置坯组编号单元格内容
            for rows in range(self.tableWidget_4.rowCount()):
                item_name = self.tableWidget_4.item(rows, 0).text()  # 获取坯组编号的名称
                if item_name == unique_labels[item]:
                    item1 = QTableWidgetItem(str(new_data[item]))
                    self.tableWidget_4.setItem(rows, 0, item1)       # 设置坯组编号单元格内容
        self.hebing(self.tableWidget_3)        # 合并首列同类项
        self.hebing1(self.tableWidget_4)     # 合并首列同类项


    def pushButton_15_clicked(self):         # A 坯组编号分解按钮事件
        # 分解第一步：将所有坯组编号归位
        global duoxuan
        global min_pizu
        # 提取字符串的后两位数字部分
        prefix = min_pizu[:-2]  # 获取去掉最后两位的前缀部分
        num_str = min_pizu[-2:]  # 获取最后两位数字部分
        # 将数字部分转换为整数
        num = int(num_str)
        for pizu, xingxi in self.Thread1.pizu_change.items():  # 存储字典的信息归位
            xingxi["pizu"] = prefix + f"{num:02d}"
            xingxi["1"] = "1"
            xingxi["2"] = "2"
            xingxi["3"] = "3"
            xingxi["4"] = "4"
            xingxi["max_bian"] = 4
            num = num + 1
        self.thread_finished()

    def pushButton_19_clicked(self):         # B枪 坯组编号分解按钮事件
        # 分解第一步：将所有坯组编号归位
        global duoxuan
        global min_pizu
        # 提取字符串的后两位数字部分
        prefix = min_pizu[:-2]  # 获取去掉最后两位的前缀部分
        num_str = min_pizu[-2:]  # 获取最后两位数字部分
        # 将数字部分转换为整数
        num = int(num_str)
        for pizu, xingxi in self.Thread1_B.pizu_change.items():  # 存储字典的信息归位
            xingxi["pizu"] = prefix + f"{num:02d}"
            xingxi["1"] = "1"
            xingxi["2"] = "2"
            xingxi["3"] = "3"
            xingxi["4"] = "4"
            xingxi["max_bian"] = 4
            num = num + 1
        self.thread_finished_B()

    def pushButton_26_clicked(self):         # 重新运算按下事件
        # 将无分配临时编号输入多线程运算进行运算
        # print("self.wfp_allocated_name_A", self.wfp_allocated_name_A)
        # print("self.wfp_allocated_name_B", self.wfp_allocated_name_B)
        self.Thread1.To_be_allocated_name = self.wfp_allocated_name_A
        self.Thread1_B.To_be_allocated_name = self.wfp_allocated_name_B
        self.Thread1.start()
        self.Thread1_B.start()

    # --------------------json操作事件------------------
    def load_sqls(self):        # 读取账号文件信息
        with open(self.USER_DATA_FILE, 'r', encoding='utf-8') as file:
            data = json.load(file)
        return data['sql']

    def save_sqls(self, sqls):  # 存储用户
        with open(self.USER_DATA_FILE, 'w', encoding='utf-8') as file:
            json.dump({"sql": sqls}, file, indent=4)
    # ------------------------------------------------